package com.example.pt.service;

import com.example.pt.dto.CommentDTO;
import com.example.pt.entity.Comment;
import com.example.pt.entity.CommentLike;
import com.example.pt.entity.User;
import com.example.pt.entity.UserLevel;
import com.example.pt.mapper.CommentLikeMapper;
import com.example.pt.mapper.CommentMapper;
import com.example.pt.repository.UserRepositories;
import com.example.pt.utils.DownloadUrlUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 评论服务类
 */
@Service
public class CommentService {

    @Autowired
    private CommentMapper commentMapper;
    
    @Autowired
    private CommentLikeMapper commentLikeMapper;
    
    @Autowired
    private UserRepositories userRepositories;

    @Autowired
    private DownloadUrlUtils downloadUrlUtils;

    
    /**
     * 获取种子的评论列表（包含回复）
     * @param torrentId 种子ID
     * @param currentUserId 当前用户ID，用于判断是否已点赞
     * @return 评论列表
     */
    public List<CommentDTO> getCommentsByTorrentId(Integer torrentId, Integer currentUserId) {
        // 获取种子下的所有评论（包括根评论和回复）
        List<Comment> allComments = commentMapper.selectAllByTorrentId(torrentId);
        
        // 将评论按照commentId存入map，方便后续构建评论树
        Map<Integer, CommentDTO> commentMap = new HashMap<>();
        
        // 第一步：转换所有评论为DTO，并放入map
        for (Comment comment : allComments) {
            CommentDTO dto = convertToDTO(comment, currentUserId);
            dto.setReplies(new ArrayList<>());
            commentMap.put(dto.getCommentId(), dto);
        }
        
        // 第二步：构建评论树
        List<CommentDTO> rootComments = new ArrayList<>();
        
        for (Comment comment : allComments) {
            CommentDTO dto = commentMap.get(comment.getCommentId());
            
            if (comment.getParentId() == null) {
                // 这是根评论
                rootComments.add(dto);
            } else {
                // 这是回复，添加到父评论的replies列表中
                CommentDTO parentDto = commentMap.get(comment.getParentId());
                if (parentDto != null) {
                    parentDto.getReplies().add(dto);
                }
            }
        }
        
        // 按创建时间排序根评论（最新的排在前面）
        rootComments.sort((c1, c2) -> c2.getCreateTime().compareTo(c1.getCreateTime()));
        
        // 对每个评论的回复列表按时间排序（最早的排在前面）
        for (CommentDTO rootComment : rootComments) {
            sortRepliesByTimeAsc(rootComment);
        }
        
        return rootComments;
    }
    
    /**
     * 递归对回复列表按时间排序
     * @param comment 评论DTO
     */
    private void sortRepliesByTimeAsc(CommentDTO comment) {
        if (comment.getReplies() != null && !comment.getReplies().isEmpty()) {
            comment.getReplies().sort((c1, c2) -> c1.getCreateTime().compareTo(c2.getCreateTime()));
            
            // 递归处理每个回复的回复
            for (CommentDTO reply : comment.getReplies()) {
                sortRepliesByTimeAsc(reply);
            }
        }
    }
    
    /**
     * 添加评论
     * @param torrentId 种子ID
     * @param userId 用户ID
     * @param content 评论内容
     * @param parentId 父评论ID，如果是根评论则为null
     * @return 添加的评论
     * @throws IllegalArgumentException 如果用户权限不足或评论不存在
     */
    @Transactional
    public CommentDTO addComment(Integer torrentId, Integer userId, String content, Integer parentId) {
        // 检查用户等级权限
        User user = userRepositories.findByUid(userId);
        if (user == null) {
            throw new IllegalArgumentException("用户不存在");
        }
        
        // 获取用户等级并检查评论权限
        UserLevel userLevel = UserLevel.getLevelById(user.getLevel());
        if (!userLevel.canComment()) {
            throw new IllegalArgumentException("您的用户等级不足，无法发表评论。需要普通用户及以上等级才能评论。");
        }
        
        // 如果是回复评论，验证父评论是否存在
        if (parentId != null) {
            Comment parentComment = commentMapper.selectById(parentId);
            if (parentComment == null || parentComment.getStatus() != 0) {
                throw new IllegalArgumentException("父评论不存在或已被删除");
            }
        }
        
        Comment comment = new Comment();
        comment.setTorrentId(torrentId);
        comment.setUserId(userId);
        comment.setContent(content);
        comment.setCreateTime(new Date());
        comment.setParentId(parentId);
        comment.setLikeCount(0);
        comment.setStatus(0); // 0-正常状态
        
        commentMapper.insert(comment);
        
        return convertToDTO(comment, userId);
    }
    
    /**
     * 点赞评论
     * @param commentId 评论ID
     * @param userId 用户ID
     * @return 是否成功
     */
    @Transactional
    public boolean likeComment(Integer commentId, Integer userId) {
        // 检查评论是否存在
        Comment comment = commentMapper.selectById(commentId);
        if (comment == null || comment.getStatus() != 0) {
            return false;
        }
        
        // 检查是否已经点赞
        CommentLike existingLike = commentLikeMapper.selectByCommentIdAndUserId(commentId, userId);
        
        if (existingLike == null) {
            // 创建新的点赞记录
            CommentLike like = new CommentLike();
            like.setCommentId(commentId);
            like.setUserId(userId);
            like.setCreateTime(new Date());
            like.setStatus(0); // 0-已点赞
            commentLikeMapper.insert(like);
        } else if (existingLike.getStatus() == 1) {
            // 已取消的点赞，恢复点赞
            commentLikeMapper.restoreLike(commentId, userId);
        } else {
            // 已经点赞，不做处理
            return true;
        }
        
        // 更新评论点赞数
        comment.setLikeCount(comment.getLikeCount() + 1);
        commentMapper.updateById(comment);
        
        return true;
    }
    
    /**
     * 取消点赞
     * @param commentId 评论ID
     * @param userId 用户ID
     * @return 是否成功
     */
    @Transactional
    public boolean unlikeComment(Integer commentId, Integer userId) {
        // 检查评论是否存在
        Comment comment = commentMapper.selectById(commentId);
        if (comment == null || comment.getStatus() != 0) {
            return false;
        }
        
        // 检查是否已点赞
        CommentLike existingLike = commentLikeMapper.selectByCommentIdAndUserId(commentId, userId);
        
        if (existingLike != null && existingLike.getStatus() == 0) {
            // 取消点赞
            commentLikeMapper.cancelLike(commentId, userId);
            
            // 更新评论点赞数
            comment.setLikeCount(Math.max(0, comment.getLikeCount() - 1));
            commentMapper.updateById(comment);
            
            return true;
        }
        
        return false;
    }
    
    /**
     * 删除评论
     * @param commentId 评论ID
     * @param userId 用户ID，用于权限校验
     * @return 是否成功
     */
    @Transactional
    public boolean deleteComment(Integer commentId, Integer userId) {
        Comment comment = commentMapper.selectById(commentId);
        
        // 检查评论是否存在且为当前用户创建
        if (comment == null || !comment.getUserId().equals(userId)) {
            return false;
        }
        
        // 递归删除所有子回复
        deleteCommentAndReplies(commentId);
        
        return true;
    }
    
    /**
     * 递归删除评论及其所有子回复
     * @param commentId 评论ID
     */
    private void deleteCommentAndReplies(Integer commentId) {
        // 查找该评论的所有回复
        List<Comment> replies = commentMapper.selectRepliesByParentId(commentId);
        
        // 递归删除每个回复及其子回复
        for (Comment reply : replies) {
            deleteCommentAndReplies(reply.getCommentId());
        }
        
        // 逻辑删除当前评论
        Comment comment = new Comment();
        comment.setCommentId(commentId);
        comment.setStatus(1); // 1-已删除
        commentMapper.updateById(comment);
    }
    
    /**
     * 将评论实体转换为DTO
     * @param comment 评论实体
     * @param currentUserId 当前用户ID
     * @return 评论DTO
     */
    private CommentDTO convertToDTO(Comment comment, Integer currentUserId) {
        CommentDTO dto = new CommentDTO();
        dto.setCommentId(comment.getCommentId());
        dto.setTorrentId(comment.getTorrentId());
        dto.setUserId(comment.getUserId());
        dto.setContent(comment.getContent());
        dto.setCreateTime(comment.getCreateTime());
        dto.setParentId(comment.getParentId());
        dto.setLikeCount(comment.getLikeCount());
        dto.setStatus(comment.getStatus());
        
        // 判断当前用户是否已点赞
        boolean hasLiked = commentMapper.checkUserLiked(comment.getCommentId(), currentUserId) > 0;
        dto.setHasLiked(hasLiked);
        
        // 获取评论用户信息
        User user = userRepositories.findByUid(comment.getUserId());
        if (user != null) {
            dto.setUsername(user.getUsername());

            String headShotUrl = downloadUrlUtils.generateDownloadLink(user.getUid());

            dto.setUserHeadshot(headShotUrl);
        }
        
        // 如果是回复，获取父评论用户名
        if (comment.getParentId() != null) {
            Comment parentComment = commentMapper.selectById(comment.getParentId());
            if (parentComment != null) {
                User parentUser = userRepositories.findByUid(parentComment.getUserId());
                if (parentUser != null) {
                    dto.setParentUsername(parentUser.getUsername());
                }
            }
        }
        
        return dto;
    }

    public List<Comment> searchCommentsByUid(int uid) {
        List<Comment> commentList = commentMapper.searchUserComments(uid);
        return commentList;
    }

    public List<Comment> getReplyCommentsByCommentId(int commentId){
        List<Comment> commentList = commentMapper.selectRepliesByParentId(commentId);
        return commentList;
    }

    /**
     * 根据commentid获取点赞的用户
     * @param commentId
     * @return 点赞的userid的列表
     */
    public List<Integer> getLikeUserIds(int commentId){
        List<Integer> userIds = commentLikeMapper.getUserIdsByCommentId(commentId);
        return userIds;
    }

    public Date getCreateTime(int commentId, int uid) {
        CommentLike commentLike = commentLikeMapper.selectByCommentIdAndUserId(commentId, uid);
        if(commentLike != null) {
            Date dateTime = commentLike.getCreateTime();
            return dateTime;
        }
        return null;
    }

    /**
     * 获取用户收到的点赞信息
     * @param userId 用户ID
     * @return 点赞信息列表
     */
    public List<Map<String, Object>> getUserReceivedLikes(Integer userId) {
        // 1. 获取用户的所有评论
        List<Comment> userComments = commentMapper.searchUserComments(userId);
        
        List<Map<String, Object>> receivedLikes = new ArrayList<>();
        
        // 2. 对每个评论，获取点赞信息
        for (Comment comment : userComments) {
            List<Integer> likeUserIds = commentLikeMapper.getUserIdsByCommentId(comment.getCommentId());
            
            // 只处理有点赞的评论
            if (likeUserIds != null && !likeUserIds.isEmpty()) {
                for (Integer likeUserId : likeUserIds) {
                    // 获取点赞用户信息
                    User likeUser = userRepositories.findById(likeUserId).orElse(null);
                    if (likeUser != null) {
                        // 获取点赞时间
                        Date likeTime = getCreateTime(comment.getCommentId(), likeUserId);
                        
                        Map<String, Object> likeInfo = new HashMap<>();
                        likeInfo.put("commentId", comment.getCommentId());
                        likeInfo.put("content", comment.getContent());
                        likeInfo.put("torrentId", comment.getTorrentId());
                        likeInfo.put("likeUserId", likeUserId);
                        likeInfo.put("likeUsername", likeUser.getUsername());
                        likeInfo.put("likeUserHeadshot", downloadUrlUtils.generateDownloadLink(likeUserId));
                        likeInfo.put("likeTime", likeTime);
                        
                        receivedLikes.add(likeInfo);
                    }
                }
            }
        }
        
        // 按点赞时间排序（最新的在前）
        receivedLikes.sort((like1, like2) -> ((Date) like2.get("likeTime")).compareTo((Date) like1.get("likeTime")));
        
        return receivedLikes;
    }
    
    /**
     * 获取用户评论收到的回复
     * @param userId 用户ID
     * @return 回复信息列表
     */
    public List<Map<String, Object>> getUserReceivedReplies(Integer userId) {
        // 1. 获取用户的所有评论
        List<Comment> userComments = commentMapper.searchUserComments(userId);
        
        List<Map<String, Object>> receivedReplies = new ArrayList<>();
        
        // 2. 对每个评论，获取回复信息
        for (Comment comment : userComments) {
            List<Comment> replies = commentMapper.selectRepliesByParentId(comment.getCommentId());
            
            // 只处理有回复的评论
            if (replies != null && !replies.isEmpty()) {
                for (Comment reply : replies) {
                    // 获取回复用户信息
                    User replyUser = userRepositories.findById(reply.getUserId()).orElse(null);
                    if (replyUser != null) {
                        Map<String, Object> replyInfo = new HashMap<>();
                        replyInfo.put("commentId", comment.getCommentId());
                        replyInfo.put("replyId", reply.getCommentId());
                        replyInfo.put("content", comment.getContent());
                        replyInfo.put("replyContent", reply.getContent());
                        replyInfo.put("torrentId", comment.getTorrentId());
                        replyInfo.put("replyUserId", reply.getUserId());
                        replyInfo.put("replyUsername", replyUser.getUsername());
                        replyInfo.put("replyUserHeadshot", downloadUrlUtils.generateDownloadLink(reply.getUserId()));
                        replyInfo.put("replyTime", reply.getCreateTime());
                        
                        receivedReplies.add(replyInfo);
                    }
                }
            }
        }
        
        // 按回复时间排序（最新的在前）
        receivedReplies.sort((reply1, reply2) -> ((Date) reply2.get("replyTime")).compareTo((Date) reply1.get("replyTime")));
        
        return receivedReplies;
    }
} 